package sharemem

import (
	"encoding/base64"
	"math"
	"runtime"
	"server_cluster/logic/db"
	"strings"
	"sync/atomic"
	"time"

	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
	"server_cluster/common/tools"
)

const (
	ITEM_EXPIRE_RANGE = 10
)

const (
	USER_ITEM_NORMAL  = 500
	USER_ITEM_SPECIAL = 50
	USER_EQUIP        = 500
	USER_EQUIP_JEWEL  = 500
	USER_WEAPON       = 500
	TEAM_MAX          = 10
	MAIL_MAX          = 100
	ROLE_MAX          = 50
	SCENE_MAX         = 50
	BUILDING_MAX      = 50
	CLIENT_DATA_LEN   = 1024 * 1024
)

type User struct {
	Index           int32                        // shm内user所在数组索引下标
	Id              MyInt64                      // uid
	Name            [20]rune                     // 玩家昵称
	Gold            int64                        // 金币
	Gem             MyInt32                      // 钻石
	Level           int16                        // 玩家等级
	Exp             int32                        // 玩家经验
	SceneId         int32                        // 当前所在场景id
	TeamId          int32                        // 当前队伍id
	Created         int64                        // 创号时间
	IsOnline        bool                         // 是否在线
	FreeNet         bool                         // 冻结网络
	LastOfflineTime int64                        // 上一次离线时间
	Kick            bool                         // 下线标志
	Clear           bool                         // 清档标志
	IsGmUser        bool                         // 是否能执行gm命令
	GateServerId    int16                        // gate服sid
	Item            UserItem                     // 道具
	Role            [ROLE_MAX]Role               // 角色列表
	Equip           [USER_EQUIP]Equip            // 装备列表
	EquipJewel      [USER_EQUIP_JEWEL]EquipJewel // 装备宝石列表
	Team            [TEAM_MAX]Team               // 队伍列表
	ClientData      [CLIENT_DATA_LEN]byte        // 客户端存档数据
	Mail            [MAIL_MAX]Mail               // 邮件列表
	CurrMailId      int32                        // 当前邮件id
	GlobalMailId    uint64                       // 已领取的最大全服邮件id
	TimerMailId     uint64                       // 已领取的最大定时邮件id

	UserScene    UserScene    // 场景
	UserQuest    UserQuest    // 任务
	UserShop     UserShop     // 商店
	UserGacha    UserGacha    // 抽卡
	UserCodex    UserCodex    // 图鉴
	UserWeapon   UserWeapon   // 武器
	UserHome     UserHome     // 家园
	UserActivity UserActivity // 活动
}

func (u *User) GetUid() int64 {
	return u.Id.NewVal
}

func (u *User) MemInit(index int32) {
	// TODO try to fix bug "fatal error: found pointer to free object"
	runtime.GC()

	u.Index = index
	u.Id.NewVal = 0
	u.Id.OldVal = 0
	u.Id.Status = 0
	for i := 0; i < len(u.Name); i++ {
		u.Name[i] = 0
	}
	u.Gold = 0
	u.Gem.NewVal = 0
	u.Gem.OldVal = 0
	u.Level = 0
	u.Exp = 0
	u.SceneId = 0
	u.TeamId = 0
	u.Created = 0
	u.IsOnline = false
	u.FreeNet = false
	u.LastOfflineTime = 0
	u.Kick = false
	u.Clear = false
	u.IsGmUser = false
	u.GateServerId = 0
	for i := 0; i < len(u.Item.Normal); i++ {
		u.Item.Normal[i].MemInit()
	}
	for i := 0; i < len(u.Item.Special); i++ {
		u.Item.Special[i].MemInit()
	}
	for i := 0; i < len(u.Role); i++ {
		u.Role[i].MemInit()
	}
	for i := 0; i < len(u.Equip); i++ {
		u.Equip[i].MemInit()
	}
	for i := 0; i < len(u.EquipJewel); i++ {
		u.EquipJewel[i].MemInit()
	}

	for i := 0; i < len(u.Team); i++ {
		u.Team[i].MemInit()
	}
	for i := 0; i < len(u.ClientData); i++ {
		u.ClientData[i] = 0
	}
	for i := 0; i < len(u.Mail); i++ {
		u.Mail[i].MemInit()
	}
	u.CurrMailId = 0
	u.GlobalMailId = 0
	u.TimerMailId = 0

	u.UserScene.MemInit()
	u.UserQuest.MemInit()
	u.UserShop.MemInit()
	u.UserGacha.MemInit()
	u.UserCodex.MemInit()
	u.UserWeapon.MemInit()
	u.UserHome.MemInit()
	u.UserActivity.MemInit()
}

func (u *User) CleanUser() {
	uid := u.GetUid()
	logger.Info("clear user, uid: %v", uid)
	index := u.Index
	SemWait(&(MyShm.SemUser[index]))

	u.MemInit(index)

	DelUser(uid)

	SemPost(&(MyShm.SemUser[index]))
}

func (u *User) IsUse() bool {
	return u.Id.NewVal > 0
}

func (u *User) IsMe(uid int64) bool {
	return u.Id.NewVal == uid
}

func (u *User) CheckSelf(uid int64) bool {
	if !u.IsMe(uid) {
		return false
	}
	SemWait(&(MyShm.SemUser[u.Index]))
	// 锁后再判断 保证安全
	if !u.IsMe(uid) {
		SemPost(&(MyShm.SemUser[u.Index]))
		return false
	}
	SemPost(&(MyShm.SemUser[u.Index]))
	return true
}

// SetSync 设置数据库同步标识
func (u *User) SetSync() {
	atomic.AddUint32(&(u.Id.Status), 1)
}

func (u *User) ClearUserWithOutLock() {
	dbUser := db.DbUser{
		Id: u.Id.NewVal,
	}
	index := u.Index
	u.MemInit(index)
	dbUser.UpdateServer(0)
}

func (u *User) AcceptGlobalMail() {
	var maxMailId int32 = 0
	for _, mailConfig := range gdconf.GetMailConfigMap() {
		if mailConfig.SendType != gdconf.MailSendTypeFree {
			continue
		}
		if uint64(mailConfig.MailId) <= u.GlobalMailId {
			continue
		}
		itemMap := make(map[int32]int32)
		for _, item := range mailConfig.ItemList {
			itemMap[item.ItemId] += item.ItemCount
		}
		expireTime := uint32(0)
		if mailConfig.ExpireHour != 0 {
			expireTime = uint32(MyShm.TimeNow + int64(mailConfig.ExpireHour*3600))
		}
		ok, _ := u.AddMail(mailConfig.Title, mailConfig.Content, mailConfig.Sender, expireTime, mailConfig.Importance, itemMap)
		if !ok {
			logger.Error("add global server mail fail, uid: %v", u.GetUid())
			continue
		}
		if maxMailId < mailConfig.MailId {
			maxMailId = mailConfig.MailId
		}
	}
	if maxMailId != 0 {
		// 刷新当前id
		u.GlobalMailId = uint64(maxMailId)
	}
}

func (u *User) OnOffline() {
	logger.Info("user offline, uid: %v", u.GetUid())
	u.IsOnline = false
	u.LastOfflineTime = tools.TimeNow()
	u.SetSync()
}

func (u *User) UserDataInit() {
	logger.Info("user online data init, uid: %v", u.GetUid())
	u.LoadUserMap()
}

// 重建用户所有索引
func (u *User) LoadUserMap() {
	u.ResetItemMap()
	u.ResetQuestMap()
	u.ResetShopMap()
	u.ResetEquipMap()
	u.ResetEquipJewelMap()
	u.ResetRoleMap()
	u.ResetSceneMap()
	u.RestCodexMap()
	u.ResetWeaponMap()
	u.ResetHomeMap()
	u.ResetActivity()
}

func (i *Item) GetItemKey() int32 {
	return i.GetId()*ITEM_EXPIRE_RANGE + int32(i.Day)
}

func (u *User) ResetItemMap() {
	var i int16
	u.InitItemNormalMap()
	for i = 0; i < USER_ITEM_NORMAL; i++ {
		if u.Item.Normal[i].Id.NewVal != 0 {
			u.SetItemNormalMap(u.Item.Normal[i].GetItemKey(), i)
		}
	}
	u.InitItemSpecialMap()
	for i = 0; i < USER_ITEM_SPECIAL; i++ {
		if u.Item.Special[i].Id.NewVal != 0 {
			u.SetItemSpecialMap(u.Item.Special[i].GetItemKey(), i)
		}
	}
}

func (u *User) ResetQuestMap() {
	for index := range u.UserQuest.MainQuestList {
		parentQuest := &u.UserQuest.MainQuestList[index]
		if parentQuest.ParentQuestId == 0 {
			continue
		}
		u.addParentQuest(parentQuest)
	}

	for index := range u.UserQuest.SideQuestList {
		parentQuest := &u.UserQuest.SideQuestList[index]
		if parentQuest.ParentQuestId == 0 {
			continue
		}
		u.addParentQuest(parentQuest)
	}

	for index := range u.UserQuest.DailyQuestList {
		parentQuest := &u.UserQuest.DailyQuestList[index]
		if parentQuest.ParentQuestId == 0 {
			continue
		}
		u.addParentQuest(parentQuest)
	}
	for _, id := range u.UserQuest.ParentQuestFinishList {
		if id == 0 {
			continue
		}
		u.AddParentQuestFinish(id)
	}
}

func (u *User) ResetShopMap() {
	for index := range u.UserShop.BuyGoodsList {
		shop := &u.UserShop.BuyGoodsList[index]
		if !shop.IsUse() {
			continue
		}
		u.AddBuyShopRecord(shop.GoodsId, shop)
	}
}

func (u *User) ResetEquipMap() {
	for index := range u.Equip {
		equip := &(u.Equip[index])
		if !equip.IsUse() {
			continue
		}
		u.Add2EquipMap(BuildEquipKey(equip.GetId(), int32(index)), equip)
	}
}

func (u *User) ResetEquipJewelMap() {
	for index := range u.EquipJewel {
		equipJewel := &(u.EquipJewel[index])
		if !equipJewel.IsUse() {
			continue
		}
		u.Add2EquipJewelMap(BuildEquipJewelKey(equipJewel.GetId(), int32(index)), equipJewel)
	}
}

func (u *User) ResetRoleMap() {
	for index := range u.Role {
		role := &(u.Role[index])
		if !role.IsUse() {
			continue
		}
		u.Add2RoleMap(role.GetId(), role)
	}
}

func (u *User) ResetSceneMap() {
	for index := range u.UserScene.SceneList {
		scene := &(u.UserScene.SceneList[index])
		if !scene.IsUse() {
			continue
		}
		u.Add2SceneMap(scene.SceneId, scene)
		for indexChild := range scene.MonsterList {
			subUnit := &(scene.MonsterList[indexChild])
			if !subUnit.IsUse() {
				continue
			}
			u.AddMonster2Map(scene.SceneId, subUnit)
		}
		for indexChild := range scene.NpcList {
			subUnit := &(scene.NpcList[indexChild])
			if !subUnit.IsUse() {
				continue
			}
			u.AddNpc2Map(scene.SceneId, subUnit)
		}
		for indexChild := range scene.GadgetList {
			subUnit := &(scene.GadgetList[indexChild])
			if !subUnit.IsUse() {
				continue
			}
			u.AddGadget2Map(scene.SceneId, subUnit)
		}
	}
}

func (u *User) RestCodexMap() {
	for index := range u.UserCodex.CodexList {
		codex := &(u.UserCodex.CodexList[index])
		if !codex.IsUse() {
			continue
		}
		u.Add2codexMap(codex.CodexId, codex)
	}
}

func (u *User) ResetWeaponMap() {
	for _, equip := range u.GetEquipMap() {
		if equip.RoleId != 0 {
			// 角色 装备列表
			equipConfig := gdconf.GetEquipConfig(equip.GetId())
			if equipConfig == nil {
				logger.Error("get equipConfig is nil, equipId: %v", equip.GetId())
				continue
			}
			equipPos := equipConfig.WeaponPos - 1
			if equipPos < 0 || equipPos > 6 {
				logger.Error("equip pos invalid, equipId: %v, pos: %v", equip.GetId(), equipConfig.WeaponPos)
				continue
			}
			role := u.GetRoleById(equip.RoleId)
			if role == nil {
				logger.Error("get role is nil, roleId: %v, uid: %v", equip.RoleId, u.GetUid())
				continue
			}
			role.EquipList[equipPos] = BuildEquipKey(equip.GetId(), equip.Cell)
		}
		if equip.JewelList[0] != 0 || equip.JewelList[1] != 0 || equip.JewelList[2] != 0 {
			// 宝石 镶嵌装备
			for _, equipJewelKey := range equip.JewelList {
				if equipJewelKey == 0 {
					continue
				}
				equipJewel := u.GetEquipJewel4Key(equipJewelKey)
				if equipJewel == nil {
					logger.Error("equip jewel not exist, equipJewelKey: %v, uid: %v", equipJewelKey, u.GetUid())
					continue
				}
				equipJewel.EquipKey = BuildEquipKey(equip.GetId(), equip.Cell)
			}
		}
		continue
	}

	for i := 0; i < len(u.UserWeapon.WeaponList); i++ {
		weapon := &(u.UserWeapon.WeaponList[i])
		if weapon.WeaponKey == 0 {
			continue
		}
		u.AddWeapon2Map(weapon.WeaponKey, weapon)
	}
	for _, weapon := range u.GetWeaponMap() {
		if weapon.RoleId != 0 {
			// 角色 武器
			role := u.GetRoleById(weapon.RoleId)
			if role == nil {
				logger.Error("get role is nil, roleId: %v, uid: %v", weapon.RoleId, u.GetUid())
				continue
			}
			role.Weapon = weapon.WeaponKey
		}
	}
}

func (u *User) ResetHomeMap() {
	for i := 0; i < len(u.UserHome.BuildingList); i++ {
		building := &(u.UserHome.BuildingList[i])
		if !building.IsUse() {
			continue
		}
		u.AddBuilding2Map(uint64(building.BuildingUuid.NewVal), building)
	}

	for i := 0; i < len(u.UserHome.UnlockBuildingList); i++ {
		unlockBuilding := &(u.UserHome.UnlockBuildingList[i])
		if !unlockBuilding.IsUse() {
			continue
		}
		u.AddUnlockBuilding2Map(unlockBuilding.BuildingId, unlockBuilding)
	}
}

func (u *User) ResetActivity() {

	for i := 0; i < len(u.UserActivity.DungeonActivityList); i++ {
		activity := &(u.UserActivity.DungeonActivityList[i])
		if !activity.IsUse() {
			continue
		}
		u.AddDungeonActivity2Map(activity)
	}

	for i := 0; i < len(u.UserActivity.DailyTaskList); i++ {
		task := &(u.UserActivity.DailyTaskList[i])
		if !task.IsUse() {
			continue
		}
		u.AddDailyTask2Map(task)
	}

	for i := 0; i < len(u.UserActivity.WeeklyTaskList); i++ {
		task := &(u.UserActivity.WeeklyTaskList[i])
		if !task.IsUse() {
			continue
		}
		u.AddWeeklyTask2Map(task)
	}

	for i := 0; i < len(u.UserActivity.SignInList); i++ {
		signIn := &(u.UserActivity.SignInList[i])
		if !signIn.IsUse() {
			continue
		}
		u.AddSignInfo2Map(signIn)
	}

	for i := 0; i < len(u.UserActivity.ZpList); i++ {
		zp := &(u.UserActivity.ZpList[i])
		if !zp.IsUse() {
			continue
		}
		u.AddZp2Map(zp)
	}
}

// 初始化索引
func (u *User) InitItemNormalMap() {
	index_game.UserMap[u.Id.NewVal].Item.Normal_map = make(map[int32]int16)
}

func (u *User) InitItemSpecialMap() {
	index_game.UserMap[u.Id.NewVal].Item.Special_map = make(map[int32]int16)
}

// 获取索引

func (u *User) GetItemNormalMap() map[int32]int16 {
	return index_game.UserMap[u.Id.NewVal].Item.Normal_map
}

func (u *User) GetItemSpecialMap() map[int32]int16 {
	return index_game.UserMap[u.Id.NewVal].Item.Special_map
}

// 保存索引

func (u *User) SetItemNormalMap(id int32, site int16) {
	if site < 0 || site >= USER_ITEM_NORMAL {
		return
	}
	index_game.UserMap[u.Id.NewVal].Item.Normal_map[id] = site
}

func (u *User) GetRemainItemNormalCell() int32 {
	return int32(USER_ITEM_NORMAL - len(index_game.UserMap[u.Id.NewVal].Item.Normal_map))
}

func (u *User) SetItemSpecialMap(id int32, site int16) {
	if site < 0 || site >= USER_ITEM_SPECIAL {
		return
	}
	index_game.UserMap[u.Id.NewVal].Item.Special_map[id] = site
}

func (u *User) GetRemainItemSpecialCell() int32 {
	return int32(USER_ITEM_SPECIAL - len(index_game.UserMap[u.Id.NewVal].Item.Special_map))
}

func (u *User) GetName() string {
	var name strings.Builder
	for _, v := range u.Name {
		if v == 0 {
			break
		}
		name.WriteRune(v)
	}
	return name.String()
}

func (u *User) SetName(name string) {
	for i := 0; i < len(u.Name); i++ {
		u.Name[i] = 0
	}
	i := 0
	for _, v := range name {
		if i == len(u.Name) {
			logger.Error("name too long, name: %v", name)
			return
		}
		u.Name[i] = v
		i++
	}
}

func (u *User) SetLevel(level int16) {
	u.Level = level
}
func (u *User) SetSceneId(sceneId int32) {
	u.SceneId = sceneId
}
func (u *User) SetCreated(created int64) {
	u.Created = created
}

func (u *User) GetClientData() string {
	var clientDataBase64 strings.Builder
	for i := 0; i < len(u.ClientData); i++ {
		if u.ClientData[i] == 0 {
			break
		}
		clientDataBase64.WriteByte(u.ClientData[i])
	}
	clientData, err := base64.StdEncoding.DecodeString(clientDataBase64.String())
	if err != nil {
		logger.Error("decode client data base64 error: %v", err)
		return ""
	}
	return string(clientData)
}

func (u *User) SetClientData(clientData string) {
	clientDataBase64 := base64.StdEncoding.EncodeToString([]byte(clientData))
	length := len(clientDataBase64)
	if length+1 >= CLIENT_DATA_LEN {
		logger.Error("client data too long, clientDataBase64: %v", clientDataBase64)
		return
	}
	for i := 0; i < length; i++ {
		u.ClientData[i] = clientDataBase64[i]
	}
	u.ClientData[length] = 0
}

func (u *User) GetParentQuestAll() map[int32]*ParentQuest {
	if index_game.UserMap[u.Id.NewVal].Quest.ParentQuestMap == nil {
		index_game.UserMap[u.Id.NewVal].Quest.ParentQuestMap = make(map[int32]*ParentQuest)
	}
	return index_game.UserMap[u.Id.NewVal].Quest.ParentQuestMap
}

func (u *User) GetParentQuest(questId int32) *ParentQuest {
	var tmp = u.GetParentQuestAll()
	return tmp[questId]
}

func (u *User) Add2ParentQuestMap(quest *ParentQuest) {
	var tmp = u.GetParentQuestAll()
	tmp[quest.ParentQuestId] = quest
}

func (u *User) DeleteParentQuest(parentQuest *ParentQuest) {
	var subQuest = u.GetSubQuest(parentQuest.ParentQuestId, parentQuest.CurrQuestId)
	if subQuest != nil {
		if subQuest.NextQuestId != 0 {
			logger.Error("ParentQuest finish but subQuest is not the Last one! nextOne is %v; parentQuestID:%v,subQuestId:%v",
				subQuest.NextQuestId, parentQuest.ParentQuestId, subQuest.QuestId)
			return
		}
	}
	delete(u.GetQuestMapAll(), parentQuest.ParentQuestId)

	var questList = u.GetSubQuestListAll()
	for _, subQuestList := range questList {
		var writeIdx = 0
		if subQuestList == nil {
			continue
		}
		for _, quest := range *subQuestList {
			if quest.ParentQuestId != parentQuest.ParentQuestId {
				(*subQuestList)[writeIdx] = quest
				writeIdx++
			}
		}
		*subQuestList = (*subQuestList)[:writeIdx]
	}

	var tmp = u.GetParentQuestAll()
	delete(tmp, parentQuest.ParentQuestId)
	parentQuest.MemInit()
}

func (u *User) CleanParentQuestFinish() {
	index_game.UserMap[u.Id.NewVal].Quest.ParentQuestFinishMap = make(map[int32]bool)
}

func (u *User) GetParentQuestFinish() map[int32]bool {
	if index_game.UserMap[u.Id.NewVal].Quest.ParentQuestFinishMap == nil {
		index_game.UserMap[u.Id.NewVal].Quest.ParentQuestFinishMap = make(map[int32]bool)
	}
	return index_game.UserMap[u.Id.NewVal].Quest.ParentQuestFinishMap
}

func (u *User) AddParentQuestFinish(questId int32) {
	var tmp = u.GetParentQuestFinish()
	tmp[questId] = true
}

func (u *User) GetSubQuestListAll() map[int16]*[]*Quest {
	if index_game.UserMap[u.Id.NewVal].Quest.SubQuestMap4Cond == nil {
		index_game.UserMap[u.Id.NewVal].Quest.SubQuestMap4Cond = make(map[int16]*[]*Quest)
	}
	return index_game.UserMap[u.Id.NewVal].Quest.SubQuestMap4Cond
}

func (u *User) GetSubQuestList4Cond(subtype int32) *[]*Quest {
	var tmp = u.GetSubQuestListAll()
	if tmp[int16(subtype)] == nil {
		var tempSlice = make([]*Quest, 0)
		tmp[int16(subtype)] = &tempSlice
	}
	return tmp[int16(subtype)]
}

func (u *User) AddSubQuestList4Cond(subtype int32, quest *Quest) {
	var tmp = u.GetSubQuestList4Cond(subtype)
	*tmp = append(*tmp, quest)
}

func (u *User) GetQuestMapAll() map[int32]map[int32]*Quest {
	if index_game.UserMap[u.Id.NewVal].Quest.QuestMap == nil {
		index_game.UserMap[u.Id.NewVal].Quest.QuestMap = make(map[int32]map[int32]*Quest)
	}
	return index_game.UserMap[u.Id.NewVal].Quest.QuestMap
}

func (u *User) GetQuestMap4ParentId(parentQuestId int32) map[int32]*Quest {
	var tmp = u.GetQuestMapAll()
	if tmp[parentQuestId] == nil {
		tmp[parentQuestId] = make(map[int32]*Quest)
	}
	return tmp[parentQuestId]
}

func (u *User) GetSubQuest(parentQuestId, questId int32) *Quest {
	var tmp = u.GetQuestMap4ParentId(parentQuestId)
	return tmp[questId]
}

func (u *User) AddQuest2QuestMap(parentQuestId int32, quest *Quest) {
	var tmp = u.GetQuestMap4ParentId(parentQuestId)
	tmp[quest.QuestId] = quest
}

func (u *User) addParentQuest(parentQuest *ParentQuest) {
	var tempQuest *Quest = nil
	for childIndex := range parentQuest.QuestList {
		quest := &(parentQuest.QuestList[childIndex])
		if quest.QuestId == 0 {
			continue
		}
		quest.ParentQuestId = parentQuest.ParentQuestId
		if tempQuest != nil {
			tempQuest.NextQuestId = quest.QuestId
		}
		tempQuest = quest

		for _, v := range quest.CondList {
			if v.Type == 0 {
				continue
			}
			u.AddSubQuestList4Cond(v.Type, quest)
			u.AddQuest2QuestMap(parentQuest.ParentQuestId, quest)
		}
	}
	u.Add2ParentQuestMap(parentQuest)
}
func (u *User) GetBuyShopRecordMap() map[int32]*ShopGoods {
	if index_game.UserMap[u.Id.NewVal].ShopBuyRecord.ShopBuyRecord == nil {
		index_game.UserMap[u.Id.NewVal].ShopBuyRecord.ShopBuyRecord = make(map[int32]*ShopGoods)
	}
	return index_game.UserMap[u.Id.NewVal].ShopBuyRecord.ShopBuyRecord
}

func (u *User) GetBuyShopRecord(shopId int32) int32 {
	var tmp = u.GetBuyShopRecordMap()
	if tmp[shopId] == nil {
		return 0
	}
	return tmp[shopId].BuyCount
}

func (u *User) AddBuyShopRecord(shopId int32, shop *ShopGoods) {
	var tmp = u.GetBuyShopRecordMap()
	tmp[shopId] = shop
}

func (u *User) DeleteBuyShopRecord(shop *ShopGoods) {
	delete(u.GetBuyShopRecordMap(), shop.GoodsId)
}

func (u *User) GetEquipMap() map[int32]*Equip {
	if index_game.UserMap[u.Id.NewVal].Equip.EquipMap == nil {
		index_game.UserMap[u.Id.NewVal].Equip.EquipMap = make(map[int32]*Equip)
	}
	return index_game.UserMap[u.Id.NewVal].Equip.EquipMap
}

func (u *User) Add2EquipMap(key int32, equip *Equip) {
	var tmp = u.GetEquipMap()
	tmp[key] = equip
}

func (u *User) DeleteEquipMap(key int32) {
	delete(u.GetEquipMap(), key)
}

func (u *User) GetEquip4Key(key int32) *Equip {
	return u.GetEquipMap()[key]
}

func (u *User) GetEquipJewelMap() map[int32]*EquipJewel {
	if index_game.UserMap[u.Id.NewVal].Equip.EquipJewelMap == nil {
		index_game.UserMap[u.Id.NewVal].Equip.EquipJewelMap = make(map[int32]*EquipJewel)
	}
	return index_game.UserMap[u.Id.NewVal].Equip.EquipJewelMap
}

func (u *User) Add2EquipJewelMap(key int32, equipJewel *EquipJewel) {
	var tmp = u.GetEquipJewelMap()
	tmp[key] = equipJewel
}

func (u *User) DeleteEquipJewelMap(key int32) {
	delete(u.GetEquipJewelMap(), key)
}

func (u *User) GetEquipJewel4Key(key int32) *EquipJewel {
	return u.GetEquipJewelMap()[key]
}

func (u *User) GetRoleMap() map[int32]*Role {
	if index_game.UserMap[u.Id.NewVal].Role.RoleMap == nil {
		index_game.UserMap[u.Id.NewVal].Role.RoleMap = make(map[int32]*Role)
	}
	return index_game.UserMap[u.Id.NewVal].Role.RoleMap
}

func (u *User) Add2RoleMap(id int32, role *Role) {
	var tmp = u.GetRoleMap()
	tmp[id] = role
}

func (u *User) DeleteRoleMap(id int32) {
	delete(u.GetRoleMap(), id)
}

func (u *User) GetRoleById(id int32) *Role {
	role := u.GetRoleMap()[id]
	if role == nil {
		logger.Info("get role is nil, roleId: %v, uid: %v", role, u.GetUid())
		return nil
	}
	return role
}

func (u *User) GetSceneMap() map[int32]*Scene {
	if index_game.UserMap[u.Id.NewVal].Scene.SceneMap == nil {
		index_game.UserMap[u.Id.NewVal].Scene.SceneMap = make(map[int32]*Scene)
	}
	return index_game.UserMap[u.Id.NewVal].Scene.SceneMap
}
func (u *User) GetSceneById(id int32) *Scene {
	return u.GetSceneMap()[id]
}

func (u *User) Add2SceneMap(id int32, scene *Scene) {
	var tmp = u.GetSceneMap()
	tmp[id] = scene
}

func (u *User) DeleteSceneMap(id int32) {
	delete(u.GetSceneMap(), id)
}

func (u *User) GetSceneMonsterMapAll() map[int32]map[int32]*Monster {
	if index_game.UserMap[u.Id.NewVal].Scene.MonsterMap == nil {
		index_game.UserMap[u.Id.NewVal].Scene.MonsterMap = make(map[int32]map[int32]*Monster)
	}
	return index_game.UserMap[u.Id.NewVal].Scene.MonsterMap
}

func (u *User) GetSceneGadgetMapAll() map[int32]map[int32]*Gadget {
	if index_game.UserMap[u.Id.NewVal].Scene.GadgetMap == nil {
		index_game.UserMap[u.Id.NewVal].Scene.GadgetMap = make(map[int32]map[int32]*Gadget)
	}
	return index_game.UserMap[u.Id.NewVal].Scene.GadgetMap
}

func (u *User) GetSceneNpcMapAll() map[int32]map[int32]*Npc {
	if index_game.UserMap[u.Id.NewVal].Scene.NpcListMap == nil {
		index_game.UserMap[u.Id.NewVal].Scene.NpcListMap = make(map[int32]map[int32]*Npc)
	}
	return index_game.UserMap[u.Id.NewVal].Scene.NpcListMap
}

func (u *User) GetSceneMonsterMap(sceneId int32) map[int32]*Monster {
	var tmp = u.GetSceneMonsterMapAll()
	if tmp[sceneId] == nil {
		tmp[sceneId] = make(map[int32]*Monster)
	}
	return tmp[sceneId]
}
func (u *User) GetSceneGadgetMap(sceneId int32) map[int32]*Gadget {
	var tmp = u.GetSceneGadgetMapAll()
	if tmp[sceneId] == nil {
		tmp[sceneId] = make(map[int32]*Gadget)
	}
	return tmp[sceneId]
}
func (u *User) GetSceneNpcMap(sceneId int32) map[int32]*Npc {
	var tmp = u.GetSceneNpcMapAll()
	if tmp[sceneId] == nil {
		tmp[sceneId] = make(map[int32]*Npc)
	}
	return tmp[sceneId]
}

func (u *User) GetSceneMonsterById(sceneId, UnitId int32) *Monster {
	var tmp = u.GetSceneMonsterMap(sceneId)
	return tmp[UnitId]
}
func (u *User) GetSceneGadgetById(sceneId, UnitId int32) *Gadget {
	var tmp = u.GetSceneGadgetMap(sceneId)
	return tmp[UnitId]
}
func (u *User) GetSceneNpcById(sceneId, UnitId int32) *Npc {
	var tmp = u.GetSceneNpcMap(sceneId)
	return tmp[UnitId]
}

func (u *User) AddMonster2Map(sceneId int32, unit *Monster) {
	var tmp = u.GetSceneMonsterMap(sceneId)
	tmp[unit.Id] = unit
}
func (u *User) AddGadget2Map(sceneId int32, unit *Gadget) {
	var tmp = u.GetSceneGadgetMap(sceneId)
	tmp[unit.Id] = unit
}
func (u *User) AddNpc2Map(sceneId int32, unit *Npc) {
	var tmp = u.GetSceneNpcMap(sceneId)
	tmp[unit.Id] = unit
}

func (u *User) GetCodexMap() map[int32]*Codex {
	if index_game.UserMap[u.Id.NewVal].Codex.CodexMap == nil {
		index_game.UserMap[u.Id.NewVal].Codex.CodexMap = make(map[int32]*Codex)
	}
	return index_game.UserMap[u.Id.NewVal].Codex.CodexMap
}

func (u *User) DeleteMonster(sceneId, UnitId int32) {
	delete(u.GetSceneMonsterMap(sceneId), UnitId)
}
func (u *User) DeleteGadget(sceneId, UnitId int32) {
	delete(u.GetSceneGadgetMap(sceneId), UnitId)
}
func (u *User) DeleteNpc(sceneId, UnitId int32) {
	delete(u.GetSceneNpcMap(sceneId), UnitId)
}

func (u *User) SetLastFishInfo(info *FishInfo) {
	index_game.UserMap[u.Id.NewVal].Scene.LastFishInfo = info
}
func (u *User) GetLastFishInfo() *FishInfo {
	return index_game.UserMap[u.Id.NewVal].Scene.LastFishInfo
}
func (u *User) GetLastFishLen() int32 {
	if index_game.UserMap[u.Id.NewVal].Scene.LastFishInfo == nil {
		return 0
	}
	return index_game.UserMap[u.Id.NewVal].Scene.LastFishInfo.FishLen
}

func (u *User) Add2codexMap(codexId int32, codex *Codex) {
	var tmp = u.GetCodexMap()
	tmp[codexId] = codex
}

func (u *User) GetCodexById(codexId int32) *Codex {
	var tmp = u.GetCodexMap()
	return tmp[codexId]
}

func (u *User) GetWeaponMap() map[uint64]*Weapon {
	if index_game.UserMap[u.Id.NewVal].Weapon.WeaponMap == nil {
		index_game.UserMap[u.Id.NewVal].Weapon.WeaponMap = make(map[uint64]*Weapon)
	}
	return index_game.UserMap[u.Id.NewVal].Weapon.WeaponMap
}

func (u *User) AddWeapon2Map(weaponKey uint64, weapon *Weapon) {
	var tmp = u.GetWeaponMap()
	tmp[weaponKey] = weapon
}
func (u *User) DeleteWeapon(weaponKey uint64) {
	delete(u.GetWeaponMap(), weaponKey)
}

func (u *User) GetWeaponByKey(key uint64) *Weapon {
	var tmp = u.GetWeaponMap()
	return tmp[key]
}
func (u *User) GetWeaponMapLen() int {
	return len(u.GetWeaponMap())
}
func (u *User) GetBuildingMap() map[uint64]*Building {
	if index_game.UserMap[u.Id.NewVal].Home.BuildingMap == nil {
		index_game.UserMap[u.Id.NewVal].Home.BuildingMap = make(map[uint64]*Building)
	}
	return index_game.UserMap[u.Id.NewVal].Home.BuildingMap
}

func (u *User) GetUnlockBuildingMap() map[int32]*UnlockBuilding {
	if index_game.UserMap[u.Id.NewVal].Home.UnlockBuildingList == nil {
		index_game.UserMap[u.Id.NewVal].Home.UnlockBuildingList = make(map[int32]*UnlockBuilding)
	}
	return index_game.UserMap[u.Id.NewVal].Home.UnlockBuildingList
}

func (u *User) AddBuilding2Map(id uint64, building *Building) {
	var tmp = u.GetBuildingMap()
	tmp[id] = building
}
func (u *User) AddUnlockBuilding2Map(id int32, building *UnlockBuilding) {
	var tmp = u.GetUnlockBuildingMap()
	tmp[id] = building
}
func (u *User) GetBuildingById(id uint64) *Building {
	var tmp = u.GetBuildingMap()
	return tmp[id]
}
func (u *User) GetUnlockBuildingById(id int32) *UnlockBuilding {
	var tmp = u.GetUnlockBuildingMap()
	return tmp[id]
}
func (u *User) DeleteBuildingById(id uint64) {
	delete(u.GetBuildingMap(), id)
}
func (u *User) GetDungeonActivityMap() map[int32]*DungeonActivity {
	if index_game.UserMap[u.Id.NewVal].Activity.DungeonActivityMap == nil {
		index_game.UserMap[u.Id.NewVal].Activity.DungeonActivityMap = make(map[int32]*DungeonActivity)
	}
	return index_game.UserMap[u.Id.NewVal].Activity.DungeonActivityMap
}
func (u *User) AddDungeonActivity2Map(activity *DungeonActivity) {
	var tmp = u.GetDungeonActivityMap()
	tmp[activity.ActivityId] = activity
}
func (u *User) GetDungeonActivityById(id int32) *DungeonActivity {
	var tmp = u.GetDungeonActivityMap()
	return tmp[id]
}

func (u *User) GetDailyTaskMap() map[int32]*Task {
	if index_game.UserMap[u.Id.NewVal].Activity.DailyTaskMap == nil {
		index_game.UserMap[u.Id.NewVal].Activity.DailyTaskMap = make(map[int32]*Task)
	}
	return index_game.UserMap[u.Id.NewVal].Activity.DailyTaskMap
}
func (u *User) AddDailyTask2Map(activity *Task) {
	var tmp = u.GetDailyTaskMap()
	tmp[activity.TaskId] = activity
}
func (u *User) GetDailyTaskById(id int32) *Task {
	var tmp = u.GetDailyTaskMap()
	return tmp[id]
}
func (u *User) ClearDailyTaskMap() {
	index_game.UserMap[u.Id.NewVal].Activity.DailyTaskMap = make(map[int32]*Task)
}
func (u *User) GetWeeklyTaskMap() map[int32]*Task {
	if index_game.UserMap[u.Id.NewVal].Activity.WeeklyTaskMap == nil {
		index_game.UserMap[u.Id.NewVal].Activity.WeeklyTaskMap = make(map[int32]*Task)
	}
	return index_game.UserMap[u.Id.NewVal].Activity.WeeklyTaskMap
}
func (u *User) AddWeeklyTask2Map(activity *Task) {
	var tmp = u.GetWeeklyTaskMap()
	tmp[activity.TaskId] = activity
}
func (u *User) GetWeeklyTaskById(id int32) *Task {
	var tmp = u.GetWeeklyTaskMap()
	return tmp[id]
}
func (u *User) ClearWeekTaskMap() {
	index_game.UserMap[u.Id.NewVal].Activity.WeeklyTaskMap = make(map[int32]*Task)
}
func (u *User) GetSignInfoMap() map[int32]*SignIn {
	if index_game.UserMap[u.Id.NewVal].Activity.SignInMap == nil {
		index_game.UserMap[u.Id.NewVal].Activity.SignInMap = make(map[int32]*SignIn)
	}
	return index_game.UserMap[u.Id.NewVal].Activity.SignInMap
}
func (u *User) AddSignInfo2Map(activity *SignIn) {
	var tmp = u.GetSignInfoMap()
	tmp[activity.ActivityId] = activity
}
func (u *User) GetSignInfoById(id int32) *SignIn {
	var tmp = u.GetSignInfoMap()
	return tmp[id]
}
func (u *User) DeleteSignInfoById(id int32) {
	delete(u.GetSignInfoMap(), id)
}
func (u *User) ClearSignInfoMap() {
	index_game.UserMap[u.Id.NewVal].Activity.SignInMap = make(map[int32]*SignIn)
}
func (u *User) GetZpMap() map[int32]*Zp {
	if index_game.UserMap[u.Id.NewVal].Activity.ZpMap == nil {
		index_game.UserMap[u.Id.NewVal].Activity.ZpMap = make(map[int32]*Zp)
	}
	return index_game.UserMap[u.Id.NewVal].Activity.ZpMap
}
func (u *User) AddZp2Map(activity *Zp) {
	var tmp = u.GetZpMap()
	tmp[activity.ActivityId] = activity
}
func (u *User) GetZpById(id int32) *Zp {
	var tmp = u.GetZpMap()
	return tmp[id]
}
func (u *User) DeleteZpById(id int32) {
	delete(u.GetZpMap(), id)
}

func (u *User) CheckUserRes(id int32, num int32) int16 {
	switch id {
	case gdconf.ITEM_EXP:
		return config.SERVER_ERROR
	case gdconf.ITEM_GEM:
		if u.Gem.NewVal < num {
			return config.ITEM_NOT_ENOUGH
		}
	case gdconf.ITEM_GOLD:
		if u.Gold < int64(num) {
			return config.ITEM_NOT_ENOUGH
		}
	default:
		return config.SERVER_ERROR
	}
	return config.OK
}

func (u *User) PacketUserInfo() *pb.User_Info {
	return &pb.User_Info{
		Gold:  u.Gold,
		Gem:   u.Gem.NewVal,
		Level: int32(u.Level),
		Exp:   u.Exp,
	}
}

func (u *User) IsFirstLoginToday() bool {
	isFirstLoginToday := true
	lastOfflineTime := time.Unix(u.LastOfflineTime, 0)
	now := time.Now()
	if lastOfflineTime.Year() == now.Year() && lastOfflineTime.YearDay() == now.YearDay() {
		isFirstLoginToday = false
	}
	return isFirstLoginToday
}

func (u *User) AddGem(num int32) {
	u.Gem.NewVal += num
}
func (u *User) AddGold(num int32) {
	u.Gold += int64(num)
}

func GetServerOpen2NowDay() int32 {
	var openServerTime = gdconf.GetConstTime("SEVERSTARTDATE")
	if openServerTime <= 0 {
		return -1
	}
	var openTimeMidNight = tools.GetMidnightSec(openServerTime)
	var subSec = tools.SubAtLeastZero(MyShm.TimeNow, openTimeMidNight)
	return int32(math.Ceil(float64(subSec+10) / 86400.0))
}

func (u *User) PackUserBaseAll() *pb.User_Base {
	return &pb.User_Base{
		Id:      u.Id.NewVal,
		Name:    u.GetName(),
		Gold:    u.Gold,
		Gem:     u.Gem.NewVal,
		Level:   int32(u.Level),
		Exp:     u.Exp,
		Scene:   u.SceneId,
		GuideId: 0,
		Pos:     &pb.Vector3{X: 0, Y: 0, Z: 0},
	}
}

func (u *User) PackUserClientData(rsp *pb.SC_Fetch) {
	rsp.ClientData = u.GetClientData()
}
